<?php

/**
 *   NIT Online Judge (C)2012-2099
 *   Developer: ACM Team @ Ningbo Institute of Technology
 *   
 *   class_core.php 2012-10-25 22:22 dgsrz@vip.qq.com
 *   
 *   Some functions copied from Discuz! (C)2009-2099 Comsenz Inc.
 *   $Origin: class_core.php 27386 2012-01-19 10:06:34Z zhengqingpeng $
 */

define('NOJ_ACCESS_PERMISSION', 1);
error_reporting(0);

class NOJ_Core {
	
	var $db = null;
	var $initated = false;
	
	function NOJ_Core() {
		$this->_init_env();
		$this->_init_config();
	}
	
	function &instance() {
		static $object = null;
		if (empty($object)) {
			$object = new NOJ_Core();
		}
		return $object;
	}
	
	function init() {
		if (!$this->initated) {
			$this->_init_db();
		}
		$this->initated = true;
	}
	
	function _init_env() {
		define('NOJ_ROOT', substr(dirname(__FILE__), 0, -12));
		
		if (!@include(NOJ_ROOT.'./source/function/function_core.php')) {
			exit('An essential file is missing.');
		}
		
		global $_G;
		$_G = array(
			'uid' => 0,
			'username' => '',
			'adminid' => 0,
			'groupid' => 0,
			'sid' => 0,
			'clientip' => $this->_get_client_ip());
	}
	
	function _init_config() {
		$_CONFIG = array();
		@include NOJ_ROOT.'./config/config.inc.php';
		if (empty($_CONFIG)) {
			runtime_error('Configuration file could not be loaded.');
		}
		$this->config = &$_CONFIG;
	}
	
	function _init_db() {
		$this->db = NOJ_DBProvider::instance();
		$this->db->setConfig($this->config['db']);
		$this->db->connect();
	}
	
	function _xss_check() {
		$temp = strtoupper(urldecode(urldecode($_SERVER['REQUEST_URI'])));
		if(strpos($temp, '<') !== false || strpos($temp, '"') !== false || strpos($temp, 'CONTENT-TRANSFER-ENCODING') !== false) {
			runtime_error('Bad request.');
		}
		return true;
	}
	
	function _get_client_ip() {
		$ip = $_SERVER['REMOTE_ADDR'];
		if (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
			$ip = $_SERVER['HTTP_CLIENT_IP'];
		} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
			foreach ($matches[0] AS $xip) {
				if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
					$ip = $xip;
					break;
				}
			}
		}
		return $ip;
	}
	
}

class NOJ_DBProvider {
	
	var $link = null;
	var $version = '';
	var $querycount = 0;
	var $config = array();
	
	function NOJ_DBProvider($config = array()) {
		if (!empty($config)) {
			$this->setConfig($config);
		}
	}
	
	function &instance() {
		static $object = null;
		if (empty($object)) {
			$object = new NOJ_DBProvider();
		}
		return $object;
	}
	
	function setConfig($config) {
		$this->config = &$config;
	}
	
	function connect() {
		if (empty($this->config)) {
			$this->halt('Configuration is incorrect. Please check.');
		}
		$this->link = $this->_dbconnect(
			$this->config['host'],
			$this->config['dbuser'],
			$this->config['dbpass'],
			$this->config['dbcharset'],
			$this->config['dbname']);
	}
	
	function _dbconnect($dbhost, $dbuser, $dbpw, $dbcharset, $dbname) {
		$link = null;
		if (!$link = @mysql_connect($dbhost, $dbuser, $dbpw, 1)) {
			$this->halt('Could not establish connection.');
		} else {
			$this->link = $link;
			if($this->version() > '4.1') {
				$dbcharset = $dbcharset ? $dbcharset : $this->config['dbcharset'];
				$serverset = $dbcharset ? 'character_set_connection='.$dbcharset.', character_set_results='.$dbcharset.', character_set_client=binary' : '';
				$serverset .= $this->version() > '5.0.1' ? ((empty($serverset) ? '' : ',').'sql_mode=\'\'') : '';
				$serverset && mysql_query("SET $serverset", $link);
			}
			$dbname && @mysql_select_db($dbname, $link);
		}
		return $link;
	}
	
	function select_db($dbname) {
		return mysql_select_db($dbname, $this->link);
	}
	
	function fetch_array($query, $result_type = MYSQL_ASSOC) {
		return mysql_fetch_array($query, $result_type);
	}
	
	function result_first($sql) {
		return $this->result($this->query($sql), 0);
	}
	
	function query($sql, $type = '') {
		$func = ($type == 'UNBUFFERED') && @function_exists('mysql_unbuffered_query') ? 'mysql_unbuffered_query' : 'mysql_query';
		if (!($query = $func($sql, $this->link))) {
			if (in_array($this->errno(), array(2006, 2013)) && substr($type, 0, 4) != 'MIKU') {
				$this->connect();  // if disconnected...
				return $this->query($sql, 'MIKU'.$type);
			}
		}
		$this->querycount++;
		return $query;
	}

	function error() {
		return (($this->link) ? mysql_error($this->link) : mysql_error());
	}

	function errno() {
		return intval(($this->link) ? mysql_errno($this->link) : mysql_errno());
	}
	
	function affected_rows() {
		return mysql_affected_rows($this->link);
	}
	
	function result($query, $row = 0) {
		$query = @mysql_result($query, $row);
		return $query;
	}
	
	function num_row($query) {
		$query = mysql_num_rows($query);
		return $query;
	}
	
	function num_fields($query) {
		return mysql_num_fields($query);
	}
	
	function free_result($query) {
		return mysql_free_result($query);
	}
	
	function insert_id($query) {
		return ($id = mysql_insert_id($this->link)) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0);
	}
	
	function fetch_rows($query) {
		$query = mysql_fetch_row($query);
		return $query;
	}
	
	function fetch_fields($query) {
		return mysql_fetch_field($query);
	}
	
	function version() {
		if (empty($this->version)) {
			$this->version = mysql_get_server_info($this->link);
		}
		return $this->version;
	}
	
	function close() {
		return mysql_close($this->link);
	}
	
	function halt($msg = '', $sql = '') {
		require_once findFile('class/error');
		NOJ_Error::db_error($msg, $sql);
	}
}

class NOJ_DB {
	
	function insert($table, $data, $return_insert_id = false, $replace = false) {
		$sql = NOJ_DB::combine_fields($data);
		$cmd = $replace ? 'REPLACE INTO' : 'INSERT INTO';
		$res = NOJ_DB::query("$cmd $table SET $sql");
		return ($return_insert_id) ? NOJ_DB::insert_id() : $res;
	}
	
	function delete($table, $condition, $limit, $unbuffered = true) {
		if (empty($condition)) {
			$where = '1';
		} elseif (is_array($condition)) {
			$where = NOJ_DB::combine_fields($condition, ' AND ');
		} else {
			$where = $condition;
		}
		$sql = "DELETE FROM ".$table." WHERE $where ".($limit ? "LIMIT $limit" : '');
		return NOJ_DB::query($sql, ($unbuffered ? 'UNBUFFERED' : ''));
	}
	
	function update($table, $data, $condition, $unbuffered = false, $low_priority = false) {
		$sql = NOJ_DB::combine_fields($data);
		$cmd = 'UPDATE '.($low_priority ? 'LOW_PRIORITY' : '');
		$where = '';
		if (!empty($condition)) {
			$where = '1';
		} elseif (is_array($condition)) {
			$where = NOJ_DB::combine_fields($condition, ' AND ');
		} else {
			$where = $condition;
		}
		return NOJ_DB::query("$cmd $table SET $sql WHERE $where", unbuffered ? 'UNBUFFERED' : '');
	}
	
	function combine_fields($array, $bound = ',') {
		$sql = $tmp = '';
		foreach ($array as $key => $value) {
			$sql .= $tmp."`$key`=`$value`";
			$tmp = $bound;
		}
		return $sql;
	}
	
	function insert_id() {
		return NOJ_DB::_exec('insert_id');
	}

	function fetch($resourceid, $type = MYSQL_ASSOC) {
		return NOJ_DB::_exec('fetch_array', $resourceid, $type);
	}

	function fetch_first($sql) {
		return NOJ_DB::_exec('fetch_first', $sql);
	}

	function result($resourceid, $row = 0) {
		return NOJ_DB::_exec('result', $resourceid, $row);
	}

	function result_first($sql) {
		return NOJ_DB::_exec('result_first', $sql);
	}

	function query($sql, $type = '') {
		return NOJ_DB::_exec('query', $sql, $type);
	}

	function num_rows($resourceid) {
		return NOJ_DB::_exec('num_rows', $resourceid);
	}

	function affected_rows() {
		return NOJ_DB::_exec('affected_rows');
	}

	function free_result($query) {
		return NOJ_DB::_exec('free_result', $query);
	}
	
	function error() {
		return NOJ_DB::_exec('error');
	}
	
	function errno() {
		return NOJ_DB::_exec('errno');
	}
	
	function security_check($sql) {
		// unrealized
		return true;
	}
	
	function _exec($func, $arg1 = '', $arg2 = '') {
		static $db = null;
		if (empty($db)) {
			$db = NOJ_DB::instance();
		}
		$result = $db->$func($arg1, $arg2);
		return $result;
	}
	
	function &instance() {
		static $db = null;
		if (empty($db)) {
			$db = new NOJ_DBProvider();
		}
		return $db;
	}
	
}

?>